#include <wxyutils.h>
#include <Windows.h>
#include <vector>
#include <OTKXString.h>
#include <logger.h>
#include <algorithm>
#include <regex>

// #ifdef UNICODE
// #define _splitpath _wsplitpath
// #endif

#define ERRFILE "ErrorMsg.txt"
_FileExt::_FileExt(const wstring &file)
{
    gconvert::uni2utf8(file, fullname);
    char drive[_MAX_DRIVE];
    char dir[_MAX_DIR];
    char fname[_MAX_FNAME];
    char ext[_MAX_EXT];
    _splitpath(fullname.c_str(), drive, dir, fname, ext);
    filepath.assign(drive).append(dir);
    filename = (string)fname;
    extension = (string)ext;
    if (extension.length() > 1)
        extension = extension.substr(1);
}
_FileExt::_FileExt(const char *file)
{
    smatch result;
    fullname.assign(file);
    //匹配目录 含结尾'/'
    regex_search(fullname, result, regex(".*[\\\\/]"))
        ? filepath = result.begin()->str()
        : filepath = string();
    //匹配文件名 不含扩展名
    regex_search(fullname, result, regex("^.+[\\\\/](.*)\\..*?$"))
        ? filename = result[1].str()
        : filename = string();
    //匹配扩展名
    regex_search(fullname, result, regex("^.+\\.(.*?)$"))
        ? extension = result[1].str()
        : extension = string();
    //匹配数字扩展名
    regex_search(fullname, result, regex("^.+\\.(\\d*?)$"))
        ? version = result[1].str()
        : version = to_string(-1);
}
pfcUICommand_ptr CreateUICommand(pfcSession_ptr Session,
                                 xrstring Name,
                                 pfcUICommandActionListener_ptr Action,
                                 xrstring MessageFile,
                                 xrstring Label,
                                 optional xrstring Help,
                                 optional xrstring Description,
                                 pfcActionListener_ptr Listener,
                                 xrstring IconFile)
{
    pfcUICommand_ptr ret;
    ret = Session->UICreateCommand(Name, Action);
    ret->Designate(MessageFile, Label, Help, Description);
    ret->AddActionListener(Listener);
    if (IconFile != NULL)
        ret->SetIcon(IconFile);
    return ret;
}

HMODULE GetSelfModuleHandle()
{
    MEMORY_BASIC_INFORMATION mbi;
    return ((::VirtualQuery(GetSelfModuleHandle, &mbi, sizeof(mbi)) != 0) ? (HMODULE)mbi.AllocationBase : NULL);
}
extern "C" _declspec(dllexport) int GetDllPath(string &Path)
{
    TCHAR curdir[MAX_PATH] = {};
    GetModuleFileName(GetSelfModuleHandle(), curdir, 100);
    TCHAR drive[_MAX_DRIVE];
    TCHAR dir[_MAX_DIR];
    TCHAR fname[_MAX_FNAME];
    TCHAR ext[_MAX_EXT];
    _splitpath(curdir, drive, dir, fname, ext);
    Path.assign(drive).append(dir);
    return 0;
}
//清理小版本
void MyPurge(string path)
{
    vector<_FileExt> files;
    ListFileByType(path.c_str(), "*", files);
    for (vector<_FileExt>::iterator it = files.begin(); it != files.end();)
    {
        try
        {
            int e1 = gconvert::str2int((*it).extension);
            int e2 = gconvert::str2int((*(it + 1)).extension);
            //判断后缀是否为数字，如果不是数字，str2int()返回0
            if (e1 == 0)
            {
                it = files.erase(it);
                continue; //防止出现连续连个后缀不为数字的文件
            }

            else if ((it + 1) != files.end() && e2 == 0)
            {
                it = files.erase(it + 1);
                continue;
            }
            else
            {
                if (strcmp((*it).filename.c_str(), (*(it + 1)).filename.c_str()) == 0) //判断文件名相同
                {
                    string file1 = (*it).fullname;
                    string file2 = (*(it + 1)).fullname;
                    wstring wfile1, wfile2;
                    //将绝对路径转为宽字符
                    gconvert::utf82uni(file1, wfile1);
                    gconvert::utf82uni(file2, wfile2);
                    string cmd;
                    //删除低版本文件，并将指针回退
                    if (e2 > e1)
                    {
                        DeleteFileW(wfile1.c_str());
                        it = files.erase(it);
                    }
                    else
                    {
                        DeleteFileW(wfile2.c_str());
                        files.erase(it + 1);
                    }
                }
                else
                    it++;
            }
        }
        catch (exception e)
        {
            LOG(LOG_ERROR) << e.what();
        }
    }
    for (vector<_FileExt>::iterator it = files.begin(); it != files.end(); it++)
    {
        _FileExt file = *it;
        string newname;
        string oldname;
        gconvert::utf82ansi(file.filepath + file.filename + ".1", newname);
        gconvert::utf82ansi(file.fullname, oldname);
        if (rename(oldname.c_str(), newname.c_str()) == -1)
            LOG(LOG_INFO) << "rename " << file.filename << "errno:" << errno;
    }
}

//根据类型获取目录下所有文件
void ListFileByType(const char *path, const char *match, vector<_FileExt> &files)
{
    //文件句柄
    intptr_t hFile = 0;
    //文件信息
    struct _finddata64i32_t fileinfo;
    string p;
    LOG(LOG_INFO) << path;
    LOG(LOG_INFO) << _findfirst(p.assign(path).append("\\").append(match).c_str(), &fileinfo);
    LOG(LOG_INFO) << _findfirst;
    LOG(LOG_INFO) << p;
    if ((hFile = _findfirst(p.assign(path).append("\\").append(match).c_str(), &fileinfo)) != -1) //查找目录下文件，并将信息存入fileinfo
    {

        do
        {
            //排除目录
            if (strcmp(fileinfo.name, ".") == 0 || strcmp(fileinfo.name, "..") == 0)
                continue;
            p.assign(path).append("\\").append(fileinfo.name);
            _FileExt file(p.c_str());
            files.push_back(file); //_FileExt自建类，包含绝对路径和扩展名
        } while (_findnext(hFile, &fileinfo) == 0);
        _findclose(hFile);
    }
    sort(files.begin(), files.end(), sortbyname);
}
//文件排序
bool sortbyname(const _FileExt &t1, const _FileExt &t2)
{
    return t1.filename < t2.filename; //升序排列
}
int CheckEnv(int count, ...)
{
    pfcSession_ptr session = pfcGetProESession();
    pfcModels_ptr Models = session->ListModels();
    pfcModel_ptr Model = session->GetCurrentModel();
    pfcModelType ModelType;
    int EnvFlag = 0;
    if (Models->getarraysize() == 0 || Model == NULL)
    {
        session->UIDisplayLocalizedMessage(ERRFILE, "Model is not found in current session!", NULL);
    }
    else if (count == 0)
    {
        if (Model->GetType() == pfcMDL_DRAWING)
        {
            EnvFlag = 1;
        }
    }
    else
    {
        va_list ap;
        va_start(ap, count);
        for (int i = 0; i < count; i++)
        {
            if (Model->GetType() == va_arg(ap, pfcModelType))
            {
                EnvFlag = 1;
                break;
            }
        }
        va_end(ap);
    }
    if (EnvFlag == 0)
    {
        LOG(LOG_WARNING) << "ModelType is error!";
        session->UIDisplayLocalizedMessage(ERRFILE, "ModelType is error!", NULL);
    }
    return EnvFlag;
}